package com.dj.controller;

import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.param.StringParam;
import com.dj.service.EncounterService;
import com.dj.util.CrudOperationUtil;
import org.hl7.fhir.dstu3.model.Encounter;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Meta;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author cyf
 * @description 就诊
 * @create 2018-06-27 10:54
 **/

@Controller
public class EncounterController {

    private static final Logger logger = LoggerFactory.getLogger(EncounterController.class);

    @Autowired
    private EncounterService encounterService;

    /**
     * 创建
     *
     * @param encounter
     * @return
     */
    @Create
    @Transactional
    public MethodOutcome create(@ResourceParam Encounter encounter) {
        long startTime = System.currentTimeMillis();
        logger.info("Encounter create start!!!");
        // 判断关联患者id是否存在
        Boolean flag = false;
        String patientId = null;
        try {
            String[] reference = encounter.getSubject().getReference().split("/");
            patientId = reference[reference.length - 1];
            flag = encounterService.isExist(patientId);
        } catch (Exception e) {
            logger.error("Exception, Query the associated patient ID error,", e);
        }
        if (flag) { //执行 create
            logger.info("relation id is exist, the id is {}", patientId);
            IdType idType = encounterService.saveEncounter(encounter);
            return CrudOperationUtil.getMethodOutcome(idType, startTime);
        } else { // 关联患者不存在
            logger.info("relation id is not exist, the id is {}", patientId);
            return CrudOperationUtil.getEmptyMethodOutcome(0);//0 - patient ;1 - encounter
            //return encounter = CrudOperationUtil.getQueryEmpty(encounter,"Encounter/"+id);
        }
        //return CrudOperationUtil.create(encounter, encounterService::saveEncounter);
    }

    /**
     * 更新
     *
     * @param theId
     * @param encounter
     * @return
     */
    @Update
    @Transactional
    public MethodOutcome update(@IdParam IdType theId, @ResourceParam Encounter encounter) {
        long startTime = System.currentTimeMillis();
        logger.info("Encounter update start!!!");
        String id = theId.getIdPart();
        IdType idType = encounterService.updateEncounter(id, encounter);
        return CrudOperationUtil.getMethodOutcome(idType, startTime);

        // 此语法为java8 ,BiFunction ，详细介绍参考：https://www.jianshu.com/p/8dc46a2dc21d
        //        传递 id, encounter 执行 updateEncounter 这方法。
        //return CrudOperationUtil.update(theId, encounter, (id, encounter) -> encounterService.updateEncounter(id, encounter));
    }

    /**
     * id读取就诊/历史
     *
     * @param theId
     * @return
     */
    @Read(version = true)
    public Encounter getByIdOrVersion(@IdParam IdType theId) {

        logger.info("Encounter getByIdOrVersion start!!!, theId={}", theId);
        String id = theId.getIdPart();

        Encounter encounter = new Encounter();
        Meta meta = new Meta();
        String version = null;
        if (theId.hasVersionIdPart()) {
            logger.info("query history!");
            version = theId.getVersionIdPart();
            Date date = encounterService.getHistoryLastUpdatTime(id, version);
            if (date != null) {
                meta.setLastUpdated(date);
                encounter = encounterService.getByIdAndVersion(id, version);
            } else {
                logger.info("Error, This historical version does not exist, the version is {}", version);
            }
        } else {
            logger.info("query the current record!");
            meta.setLastUpdated(encounterService.getLastUpdatTime(id));
            encounter = encounterService.getByEncounterId(id);
        }

        if (!encounter.isEmpty()) {
            encounter.setMeta(meta);
        } else {
            String vS = version == null ? "" : "/_history/" + version;
            encounter = CrudOperationUtil.getQueryEmpty(encounter, "Encounter/" + id + vS);
        }

        return encounter;

        //return CrudOperationUtil.readOrVRead(theId, encounterService::getById, (id, version) -> encounterService.getByIdAndVersion(id, version));
    }

    /**
     * 查询所有历史记录
     *
     * @param theId
     * @return
     */
    @History(type = Encounter.class)
    public List<Encounter> getEncounterHistory(@IdParam IdType theId) {
        logger.info("Encounter getAllEncounterHistory start!!!, theId={}", theId);
        String id = theId.getIdPart();
        return encounterService.getAllEncounterById(id);
    }

    /**
     * patient  患者姓名    读取就诊
     *
     * @param patientName
     * @return
     */
    @Search()
    public List<Encounter> searchByName(@RequiredParam(name = "subject:Patient.name") StringParam patientName) {
        logger.info("Encounter searchByName start!!!, name = {}", patientName);
        List<Encounter> encounters = encounterService.getByPatientName(patientName);
        return encounters;
    }


    /**
     * 删除
     *
     * @param theId
     * @return
     */
    @Delete(type = Encounter.class)
    @Transactional
    public MethodOutcome delete(@IdParam IdType theId) {
        long startTime = System.currentTimeMillis();
        logger.info("Encounter delete start!!!, theId={}", theId);
        return CrudOperationUtil.delete(theId, encounterService::deleteEncounter, startTime);
    }
}
